package com.topscomm.pm.script;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.google.gson.JsonArray;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.pm.PmSystemConst;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.topscomm.cbo.pojo.CboApprovalNodeInsEntity;
import com.topscomm.cbo.pojo.CboItemDetailsEntity;
import com.topscomm.cbo.pojo.CboSysParamEntity;
import com.topscomm.cbo.service.ICboItemDetailsService;
import com.topscomm.cbo.service.ICboSysParamService;
import com.topscomm.pm.PmScript;
import com.topscomm.pm.pojo.PmInvoiceApplyEntity;
import com.topscomm.pm.pojo.PmProjectEntity;
import com.topscomm.pm.service.IPmInvoiceApplyService;
import com.topscomm.pm.service.IPmProjectService;
import com.topscomm.pm.service.IPmRecBillService;
import com.topscomm.pm.service.impl.PmProjectService;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.DateUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.ITapService;
import com.topscomm.tap.TapEntity;
import com.topscomm.tap.common.ParameterCache;

/**
 *
* @ClassName: PmErpScript
* @Description: 工程项目管理系统调用ERP服务平台 脚本类
* @author fanzm
* @date 2020年7月16日 下午5:50:38
*
 */
@Component
public class PmErpScript extends PmScript {

    @Autowired
    private PmProjectService pmProjectService;

    /**
    * @Title: pmAddErpItem
    * @Description: 项目立项通过后，自动调用ERP服务，增加料品档案
    * 参数：组织、料号为项目号，品名为项目名称
    * @author fanzm
    * @date  2020年6月18日 下午2:36:32
    * @param service
    * @param entity
    * @throws Exception
    * @throws
     */
    @Transactional(rollbackFor = Exception.class)
    public void pmAddErpItem(ITapService service, TapEntity entity) throws Exception {
        // 审批节点实例
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        PmProjectService pmProjectService = (PmProjectService) SpringUtil.getBean("pmProjectService");
        PmProjectEntity pmProjectEntity = pmProjectService.queryById(sourceId);
        if (pmProjectEntity != null) {
            String orgcode = pmProjectEntity.getOwnerorgcode();
            JSONObject map = new JSONObject();
            map.put("system", "pm");
            map.put("ident", pmProjectEntity.getTableName()+"_"+pmProjectEntity.getId());
            map.put("orgcode", orgcode);
            map.put("inventoryuomgroup", 5);//库存主单位计量单位组
            map.put("inventoryUOMCode", "PCS");//库存主单位
            map.put("inventoryseconduomcode", "PCS");//库存主单位
            map.put("code",pmProjectEntity.getCode() );
            map.put("name",pmProjectEntity.getName());
            map.put("itemformattribute", "10");//制造件
            map.put("bomenable", false);//是否可BOM
            map.put("inventoryenable",true);//是否可库存交易
            map.put("mrpenable", false);//是否可MRP
            map.put("outsideoperationenable", false);//是否可委外
            map.put("purchaseenable", false);//是否可采购
            map.put("salesenable", true);//可销售

            if("D1".equals(orgcode))//股份
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("assetcategorycode", "07");//财务分类 07安装服务 06技术服务 05资产
                map.put("productioncategorycode", "A03");//生产分类 其他
            }else if("D22".equals(orgcode))//电力工程
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("assetcategorycode", "22C03");//财务分类 07安装服务 06技术服务 05资产
                map.put("productioncategorycode", "A03");//生产分类 其他
            } else if("D22F01".equals(orgcode))//四川
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("productioncategorycode", "A03");//生产分类 其他
            } else if("D22F02".equals(orgcode))//重庆
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("productioncategorycode", "A03");//生产分类 其他
            }  else if("D22F03".equals(orgcode))//河北
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("productioncategorycode", "A03");//生产分类 其他
            }  else if("D22F04".equals(orgcode))//湖南
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("productioncategorycode", "A03");//生产分类 其他
            }  else if("D26".equals(orgcode))//科远
            {
                map.put("StockCategoryCode", "K22");//库存分类 运维服务
                map.put("productioncategorycode", "A03");//生产分类 其他
            }

            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setConnectTimeout(2000);// 设置超时
            requestFactory.setReadTimeout(200000);//读取超时时间
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            String token = ParameterCache.getValue("ERPServiceUrl_Token");
            headers.set("token", token);
            //map.put("templateid", "20061200000001");
            HttpEntity<JSONObject> request = new HttpEntity<>(map, headers);

            try {
                String url = ParameterCache.getValue("ERPUrl_ItemCreate");
                ResponseEntity<JSONObject> response = restTemplate
                    .postForEntity(url, request, JSONObject.class);
                //如果失败
                if(response.getBody().getBooleanValue("success")==false)
                {
                    String errorCode = response.getBody().getString("errorCode");
                    if(!"409".equals(errorCode))//不是做单重复的
                    {
                        throw new Exception(response.getBody().getString("message"));
                    }
                }
            }
            catch(Exception e)
            {
                throw new Exception(e.getMessage());
            }
        }
    }

    /**
     * @Title: addErpAllDoc
     * @Description: 生成标准销售单
     * @author houyuhang
     * @date  2023年1月16日
     */
    public void pmAddErpSo(ITapService service, TapEntity entity) throws Exception {
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        IPmInvoiceApplyService pmInvoiceApplyService = (IPmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        PmInvoiceApplyEntity pmInvoiceApplyEntity = pmInvoiceApplyService.queryById(sourceId);
        IPmProjectService pmProjectService = (IPmProjectService) SpringUtil.getBean("pmProjectService");
        PmProjectEntity pmProjectEntity = pmProjectService.queryById(""+pmInvoiceApplyEntity.getProjectid());
        // 只有新增1需要生成u9数据，作废2重开3不需要
        if(ObjectUtil.isEmpty(pmInvoiceApplyEntity) || !"1".equals(pmInvoiceApplyEntity.getCategory()) || ObjectUtil.isEmpty(pmProjectEntity)) {
            return;
        }
        try {
            if (pmProjectEntity.getCreateon().compareTo(DateUtil.stringToDate(PmSystemConst.InvoiceApplyOnlineDate)) < 0) {
                this.pmAddErpSale(pmInvoiceApplyEntity, pmProjectEntity, "first");
            } else {
                // 料品信息修改
                this.pmUpdateErpItem(pmInvoiceApplyEntity);
                // 标准销售单
                this.pmAddErpSale(pmInvoiceApplyEntity, pmProjectEntity, "second");
                // 标准销售单审批
                this.pmAddErpSaleApproval(pmInvoiceApplyEntity);
            }
        } catch (Exception ex) {
            throw new ServiceException(ex.getMessage());
        }
    }

    /**
     * @Title:
     * @Description: 料品信息修改
     * @author houyuhang
     * @date  2023年1月16日
     */
    @Transactional(rollbackFor = Exception.class)
    public void pmUpdateErpItem(PmInvoiceApplyEntity pmInvoiceApplyEntity) throws Exception {
        IPmInvoiceApplyService pmInvoiceApplyService = (IPmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        String paraValue = ParameterCache.getValue("ERPServiceUrl_Token");
        String paraUrl = ParameterCache.getValue("ERPServiceUrl_ModifyItem");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orgcode", pmInvoiceApplyEntity.getInvoiceorgcode());
        jsonObject.put("itemCode", pmInvoiceApplyEntity.getProjectcode());
        jsonObject.put("itemFormAttribute", 17); // 服务
        jsonObject.put("inventoryPlanningMethod", 4); // MRP规划
        jsonObject.put("receiptMode", 0); // 收货程序 收货-入库
        jsonObject.put("receiptModeAllowModify", false); // 收货程序可改
        JSONObject response = pmInvoiceApplyService.remoteRequestMethod(jsonObject, paraValue, paraUrl);
        //如果失败
        if(response.getBooleanValue("success")==false) {
            throw new Exception(response.getString("message"));
        }
    }

    /**
     * @Title:
     * @Description: 开票申请，自动生成销售订单
     * @author houyuhang
     * @date  2023年1月16日
     */
    @Transactional(rollbackFor = Exception.class)
    public void pmAddErpSale(PmInvoiceApplyEntity pmInvoiceApplyEntity, PmProjectEntity pmProjectEntity, String orderStr) throws Exception {
        ICboItemDetailsService cboItemDetailsService = (ICboItemDetailsService) SpringUtil.getBean("cboItemDetailsService");
        IPmInvoiceApplyService pmInvoiceApplyService = (IPmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        IPmProjectService pmProjectService = (IPmProjectService) SpringUtil.getBean("pmProjectService");
        String orgcode = pmInvoiceApplyEntity.getInvoiceorgcode();
        String deptcode = pmInvoiceApplyEntity.getInvoicedeptcode();
        String deptname = pmInvoiceApplyEntity.getDeptname();
        String areaInfoFromCrm = pmProjectService.getAreaInfoFromCrm(deptcode,deptname);
        JSONObject map = new JSONObject();
        map.put("system", "pm");
        map.put("ident", pmInvoiceApplyEntity.getTableName()+"_"+pmInvoiceApplyEntity.getId());
        map.put("orgcode", orgcode);//开票公司
        map.put("customerCode",pmInvoiceApplyEntity.getErpcode());//客户编码
        if(StringUtil.isEmpty(pmInvoiceApplyEntity.getErpcode())) {//如果客户ERP编号为空            {
            throw new Exception("ERP客户编码不能为空！");
        }
        map.put("shipToSiteCode",pmInvoiceApplyEntity.getErpcode());//收货位置编码
        map.put("saleDepartmentCode",pmInvoiceApplyEntity.getInvoicedeptcode());//部门编码
        map.put("sellerCode","");//业务员 空着

        if("D1".equals(orgcode))//股份
        {   if ("first".equals(orderStr)) {
                map.put("documentTypecode", "SO6");//单据类型ID
            } else {
                map.put("documentTypecode", "SO1");//单据类型ID
            }
            map.put("confirmTermCode", "D001");//立账条件编码
        }else if("D22".equals(orgcode))//电力工程
        {   if ("first".equals(orderStr)) {
                map.put("documentTypecode", "SO1");//单据类型ID
            } else {
                map.put("documentTypecode", "SO6");//单据类型ID
            }
            map.put("confirmTermCode", "22D001");//立账条件编码 款到发货
        } else if("D22F01".equals(orgcode))//四川
        {
            map.put("documentTypecode", "SO6");//单据类型ID
            map.put("confirmTermCode", "22D001");//立账条件编码
        } else if("D22F02".equals(orgcode))//重庆
        {
            map.put("documentTypecode", "SO6");//单据类型ID
            map.put("confirmTermCode", "22D001");//立账条件编码
        }  else if("D22F03".equals(orgcode))//河北
        {
            map.put("documentTypecode", "SO6");//单据类型ID
            map.put("confirmTermCode", "22D001");//立账条件编码
        }  else if("D22F04".equals(orgcode))//湖南
        {
            map.put("documentTypecode", "SO6");//单据类型ID
            map.put("confirmTermCode", "22D001");//立账条件编码
        }  else if("D26".equals(orgcode))//科远
        {
            map.put("documentTypecode", "SO6");//单据类型
            map.put("confirmTermCode", "22D001");//立账条件编码
        } else {
            throw new Exception("公司单据类型未指定，请联系管理员！");
        }
        //map.put("businessDate",DateUtil.dateToString(pmInvoiceApplyEntity.getInvoicedate(), "yyyy-MM-dd HH:mm:ss"));//业务日期【yyyy-MM-dd HH:mm:ss】
        map.put("businessDate",DateUtil.Now());//业务日期【yyyy-MM-dd HH:mm:ss】
        map.put("soSrcType", "0");//来源类别编码 手工创建
        map.put("tcCode", "C001");//币种编码
        map.put("priceIncludeTax", "true");//价格是否含税
        map.put("status", "2");//状态 审核中2 审核3 开立1
        if (!StringUtil.isEmpty(pmInvoiceApplyEntity.getErpsourcecode())) {
            map.put("confirmTermCode",pmInvoiceApplyEntity.getErpsourcecode()); //立账条件的erp来源编码
        }
        //PmInvoiceType 通过编码映射
        CboItemDetailsEntity ent = cboItemDetailsService.queryObjectByWhere("itemid in (select id from CboItems where code='PmInvoiceType') and code='"+pmInvoiceApplyEntity.getInvoicetype()+"'");
        if(ent!=null)
            map.put("taxScheduleCode", ent.getExtendfield1());//税组合编码
        else
            map.put("taxScheduleCode","TS18");//默认，13%增值税专用发票

        //D1F01_0102 PmPorvinceDept 通过编码映射
        if("D1F01_0102".equals(deptcode))//陕西国电
            map.put("provinceCode", "51");//省份
        else if(deptcode.startsWith("26"))//科远
            map.put("provinceCode", "");//省份
        else
        {
            String deptcode4=deptcode.substring(0,4);
            CboItemDetailsEntity entdept = cboItemDetailsService.queryObjectByWhere("itemid in (select id from CboItems where code='PmPorvinceDept') and code='"+deptcode4+"'");
            if(entdept!=null)
                map.put("provinceCode", entdept.getExtendfield1());//省份
            else
                map.put("provinceCode","");//省份
        }

        ArrayList list = new ArrayList();
        JSONObject line = new JSONObject();
        line.put("itemInfoCode",pmProjectEntity.getCode());//料品编码
        line.put("orderByQtyTU", "1");//数量
        line.put("orderPriceTC",pmInvoiceApplyEntity.getInvoicemoney());//定价
        line.put("memo","开票要求:"+pmInvoiceApplyEntity.getDemand()+";开票说明:"+pmInvoiceApplyEntity.getExplain());//定价
        //line.put("requireDate",DateUtil.dateToString(pmInvoiceApplyEntity.getInvoicedate(), "yyyy-MM-dd HH:mm:ss"));//交期
        line.put("requireDate", DateUtil.Now());
        line.put("srcDocType", "0");//单据来源类别
        if("D1".equals(orgcode))//股份
        {
            line.put("recTermCode", "D01");//收款条件编码
        }else if("D22".equals(orgcode))//电力工程
        {
            line.put("recTermCode", "D2201");//收款条件编码
        } else if("D22F01".equals(orgcode))//四川
        {
            line.put("recTermCode", "D2201");//收款条件编码
        } else if("D22F02".equals(orgcode))//重庆
        {
            line.put("recTermCode", "D2201");//收款条件编码
        }  else if("D22F03".equals(orgcode))//河北
        {
            line.put("recTermCode", "D2201");//收款条件编码
        }  else if("D22F04".equals(orgcode))//湖南
        {
            line.put("recTermCode", "D2201");//收款条件编码
        }  else if("D26".equals(orgcode))//科远
        {
            line.put("recTermCode", "D01");//收款条件编码
        } else {
            throw new Exception("公司收款条件编码未指定，请联系管理员！");
        }
        line.put("province", map.get("provinceCode"));//行上的销售省份
        line.put("area",areaInfoFromCrm);//行上的区域
        line.put("sOType","03"); //行上的销售订单类别
        // 借出调拨单号、行号,申请人
        if ("second".equals(orderStr)) {
            line.put("descFlexFieldPrivateDescSeg2", pmInvoiceApplyEntity.getDocno());
            line.put("descFlexFieldPrivateDescSeg3", "1");
            line.put("applyUser", pmInvoiceApplyEntity.getUsername() + "[" + pmInvoiceApplyEntity.getUsercode() + "]");
        }
        list.add(line);
        map.put("SOLines", list);
        // 调用创建销售订单接口
        String paraUrl = ParameterCache.getValue("ERPServiceUrl_SaleorderCreate");
        String paraValue = ParameterCache.getValue("ERPServiceUrl_Token");
        JSONObject response = pmInvoiceApplyService.remoteRequestMethod(map, paraValue, paraUrl);
        //如果失败
        if(response.getBooleanValue("success")==false) {
            String statusCode = response.getString("statusCode");
            if(!"409".equals(statusCode))//不是做单重复的
            {
                throw new Exception(response.getString("message"));
            }
        } else {
            JSONObject result = response.getJSONObject("result");
//                  String docno =  querySODocno(erpid);
            pmInvoiceApplyEntity.setErpdocno(result.getString("docNo"));
            pmInvoiceApplyEntity.setErpid(result.getString("id"));
            pmInvoiceApplyService.updateEntity(pmInvoiceApplyEntity);
        }
    }
    /**
     * @Description: 审批销售订单
     * @author houyuhang
     * @date  2023年1月17日
     */
    @Transactional(rollbackFor = Exception.class)
    public void pmAddErpSaleApproval(PmInvoiceApplyEntity pmInvoiceApplyEntity) throws Exception {
        IPmInvoiceApplyService pmInvoiceApplyService = (IPmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        String paraUrl = ParameterCache.getValue("ERPServiceUrl_SaleApprove");
        String paraValue = ParameterCache.getValue("ERPServiceUrl_Token");
        String orgcode = pmInvoiceApplyEntity.getInvoiceorgcode();
        JSONObject map = new JSONObject();
        map.put("docNo", pmInvoiceApplyEntity.getErpdocno());
        map.put("status", 3);
        map.put("orgcode", orgcode);
        JSONObject response = pmInvoiceApplyService.remoteRequestMethod(map, paraValue, paraUrl);
        //如果失败且不是单据已审核，抛出异常
        if(response.getBooleanValue("success")==false) {
            if (!"SO040601".equals(response.getString("errorCode"))) {
                throw new Exception(response.getString("message"));
            }
        }
    }

    //根据id查询销售订单单号
    private String querySODocno(String id) throws Exception {
        String docno="";
        JSONObject map = new JSONObject();
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(2000);// 设置超时
        requestFactory.setReadTimeout(10000);//读取超时时间
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        String token = ParameterCache.getValue("DataServiceUrl_Token");
        String templateid = ParameterCache.getValue("ERPServiceUrl_SOQueryDocnoID");
        headers.set("token", token);
        map.put("templateid", templateid);
        try {
            String url = ParameterCache.getValue("ERPUrl_Query");

            JSONObject params = new JSONObject();
            params.put("query_id", id);
            map.put("paramsMap", params);

            int pageNum=1;
            int pageSize=100;
            int totalPage=0;
            map.put("pageNum",pageNum);
            map.put("pageSize", pageSize);

            HttpEntity<JSONObject> request = new HttpEntity<>(map, headers);
            ResponseEntity<JSONObject> response = restTemplate
                .postForEntity(url, request, JSONObject.class);
            if(response.getBody().getBooleanValue("success")==true)
            {
                totalPage=response.getBody().getJSONObject("result").getIntValue("totalPage");
                List<Map<String, Object>> dataList = (List)response.getBody().getJSONObject("result").getJSONArray("dataList");
                if(dataList.size()>0)
                {
                    docno = ConvertUtil.convertToString(dataList.get(0).get("docno"));
                }
                return docno;
            }
            else
                throw new Exception(response.getBody().getString("message"));
        }
        catch(Exception e)
        {
           throw new Exception(e.getMessage());
        }
    }

    //开票自动检索客户编号
    @Transactional(rollbackFor = Exception.class)
    public void pmUpdateCustomerCode(ITapService service, TapEntity entity) throws Exception {
        // 审批节点实例
        CboApprovalNodeInsEntity nodeIns = (CboApprovalNodeInsEntity) entity;
        String sourceId = ConvertUtil.convertToString(nodeIns.getSourceid());
        IPmInvoiceApplyService pmInvoiceApplyService = (IPmInvoiceApplyService) SpringUtil.getBean("pmInvoiceApplyService");
        PmInvoiceApplyEntity pmInvoiceApplyEntity = pmInvoiceApplyService.queryById(sourceId);
        String erpcode = pmInvoiceApplyEntity.getErpcode();
        if(StringUtil.isEmpty(erpcode))
        {
            JSONObject map = new JSONObject();
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setConnectTimeout(2000);// 设置超时
            requestFactory.setReadTimeout(10000);//读取超时时间
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            String token = ParameterCache.getValue("DataServiceUrl_Token");
            String templateid = ParameterCache.getValue("ERPServiceUrl_CustomerID");
            headers.set("token", token);
            map.put("templateid", templateid);
            try {
                String url = ParameterCache.getValue("ERPUrl_Query");

                JSONObject params = new JSONObject();
                params.put("orgcode", pmInvoiceApplyEntity.getInvoiceorgcode());
                params.put("customername", pmInvoiceApplyEntity.getCustomername().trim());
                map.put("paramsMap", params);

                int pageNum=1;
                int pageSize=100;
                int totalPage=0;
                map.put("pageNum",pageNum);
                map.put("pageSize", pageSize);

                HttpEntity<JSONObject> request = new HttpEntity<>(map, headers);
                ResponseEntity<JSONObject> response = restTemplate
                    .postForEntity(url, request, JSONObject.class);
                if(response.getBody().getBooleanValue("success")==true)
                {
                    totalPage=response.getBody().getJSONObject("result").getIntValue("totalPage");
                    List<Map<String, Object>> dataList = (List)response.getBody().getJSONObject("result").getJSONArray("dataList");
                    if(dataList.size()>0)
                    {
                        pmInvoiceApplyEntity.setErpcode(ConvertUtil.convertToString(dataList.get(0).get("code")));
                        pmInvoiceApplyService.updateEntity(pmInvoiceApplyEntity);
                    }
                    return;
                }
                else
                    throw new Exception(response.getBody().getString("message"));
            }
            catch(Exception e)
            {
               throw new Exception(e.getMessage());
            }
        }
    }
}
